﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.Windows.Forms;
using Microsoft.Win32;

namespace CompilerForC.SyntaxTest
{
    using LexicalAnalysis;
    using SyntaxAnalysis;
    using SyntaxAnalysis.TreeCollection;
    
    class Program
    {
        [STAThread]
        static void Main(string[] args)
        {
            string source = Properties.Resources.TestProgram;

            Lexer lexer = new Lexer();
            lexer.Tokenize(source);

            Parser parser = new Parser();
            parser.Parse(lexer.Tables);
            
            try
            {
                string parseTreeFile = String.Concat(Path.GetTempFileName(), ".png");

                SaveParseTree(parser.ParseTreeRootNode, parseTreeFile);

                ProcessStartInfo previewProcessInfo = new ProcessStartInfo();

                previewProcessInfo.Verb = "open";
                previewProcessInfo.FileName = parseTreeFile;

                Process.Start(previewProcessInfo);
            }
            catch (System.Exception ex)
            {
                MessageBox.Show(ex.Message, "Syntax Test", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }                    
            
            foreach (SyntaxError err in parser.SyntaxErrors)
                Console.WriteLine("Line: {0}, Error: {1}", err.Line, err.Description);
        }

        static void SaveParseTree(TreeNode<SyntaxNode> root, string filepath)
        {
            string dotFilePath = Path.GetTempFileName();
            
            using (StreamWriter sw = new StreamWriter(dotFilePath))
            {
                sw.WriteLine("digraph ParseTree");
                sw.WriteLine("{");

                WriteNodeAttributes(sw, root);
                
                sw.WriteLine();
                
                WriteNodeLinks(sw, root);

                sw.WriteLine("}");
            }

            string dotPath = @"C:\Program Files\Graphviz 2.21\bin\dot.exe";
            Process process = Process.Start(dotPath, String.Format("-Tpng \"{0}\" -o \"{1}\"", dotFilePath, filepath));
            process.WaitForExit();

            File.Delete(dotFilePath);
        }

        static void WriteNodeAttributes(StreamWriter sw, TreeNode<SyntaxNode> parent)
        {
            if (parent.Value.Terminal)
                sw.WriteLine(String.Format("\t{0} [label=\"{1}\", shape=box, style=filled, fillcolor=lightblue, color=black, fontname=Consolas, fontcolor=red];", parent.GetHashCode(), parent.Value.ToString()));
            else
                sw.WriteLine(String.Format("\t{0} [label=\"{1}\", shape=ellipse, style=filled, fillcolor=lightblue color=black, fontname=Consolas, fontcolor=blue];", parent.GetHashCode(), parent.Value.ToString()));

            foreach (TreeNode<SyntaxNode> child in parent.Children)
            {
                WriteNodeAttributes(sw, child);
            }
        }

        static void WriteNodeLinks(StreamWriter sw, TreeNode<SyntaxNode> parent)
        {
            foreach (TreeNode<SyntaxNode> child in parent.Children)
            {
                sw.WriteLine(String.Format("\t{0} -> {1};", parent.GetHashCode(), child.GetHashCode()));

                WriteNodeLinks(sw, child);
            }
        }
    }
}
